//我们首先解决在coo格式下的矩阵分割问题
#ifndef MATRIX_SEGMENTATION_H
#define MATRIX_SEGMENTATION_H

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//三个接口，分别获取严格上三角、严格下三角和对角线矩阵
//A矩阵的三个维度，A非零元素的数量，A中的行的数量，A必须是方阵。
void martix_csr_get_triu(float* A_csr_val, int* A_csr_row, 
int* A_csr_col, int A_no_zero_element, int A_size, 
float* A_triu_csr_val, int* A_triu_csr_row,int* A_triu_csr_col, 
int* A_triu_no_zero_element){
    //遍历行索引，然后再嵌套遍历列索引
    //分别是行索引和列索引
    int i;
    int j;

    *A_triu_no_zero_element = 0;

    //遍历行索引
    //行索引一共是0-size共size+1个，我们就遍历到索引size-1
    for(i = 0; i < A_size ; i++){
        
        //A_triu_csr_row是从0开始的，每次我们根据有效元素的数量，不断更新新的元素
        A_triu_csr_row[i] = *A_triu_no_zero_element;
        
        //遍历所有列
        for(j = A_csr_row[i]; j < A_csr_row[i+1]; j++){
            //我们看当前的列号大于行号，那就是上三角的部分
            if(A_csr_col[j] > i){
                //这里说明这个节点就是上三角矩阵的元素
                A_triu_csr_col[*A_triu_no_zero_element] = A_csr_col[j];
                A_triu_csr_val[*A_triu_no_zero_element] = A_csr_val[j];

                (*A_triu_no_zero_element)++;
            }
        }
    }

    //最后我们将row数组的最后一个元素
    A_triu_csr_row[A_size] = *A_triu_no_zero_element;
}

void martix_csr_get_tril(float* A_csr_val, int* A_csr_row, 
int* A_csr_col, int A_no_zero_element, int A_size, 
float* A_tril_csr_val, int* A_tril_csr_row,int* A_tril_csr_col, 
int* A_tril_no_zero_element){
    //遍历行索引，然后再嵌套遍历列索引
    //分别是行索引和列索引
    int i;
    int j;

    *A_tril_no_zero_element = 0;

    //遍历行索引
    //行索引一共是0-size共size+1个，我们就遍历到索引size-1
    for(i = 0; i < A_size ; i++){
        
        //A_triu_csr_row是从0开始的，每次我们根据有效元素的数量，不断更新新的元素
        A_tril_csr_row[i] = *A_tril_no_zero_element;
        
        //遍历所有列
        for(j = A_csr_row[i]; j < A_csr_row[i+1]; j++){
            //我们看当前的列号大于行号，那就是上三角的部分
            if(A_csr_col[j] < i){
                //这里说明这个节点就是上三角矩阵的元素
                A_tril_csr_col[*A_tril_no_zero_element] = A_csr_col[j];
                A_tril_csr_val[*A_tril_no_zero_element] = A_csr_val[j];

                (*A_tril_no_zero_element)++;
            }
        }
    }

    //最后我们将row数组的最后一个元素
    A_tril_csr_row[A_size] = *A_tril_no_zero_element;
}

void martix_csr_get_diag(float* A_csr_val, int* A_csr_row, 
int* A_csr_col, int A_no_zero_element, int A_size, 
float* A_diag_csr_val, int* A_diag_csr_row,int* A_diag_csr_col, 
int* A_diag_no_zero_element){
    //遍历行索引，然后再嵌套遍历列索引
    //分别是行索引和列索引
    int i;
    int j;

    *A_diag_no_zero_element = 0;

    //遍历行索引
    //行索引一共是0-size共size+1个，我们就遍历到索引size-1
    for(i = 0; i < A_size ; i++){
        
        //A_triu_csr_row是从0开始的，每次我们根据有效元素的数量，不断更新新的元素
        A_diag_csr_row[i] = *A_diag_no_zero_element;
        
        //遍历所有列
        for(j = A_csr_row[i]; j < A_csr_row[i+1]; j++){
            //我们看当前的列号大于行号，那就是上三角的部分
            if(A_csr_col[j] == i){
                //这里说明这个节点就是上三角矩阵的元素
                A_diag_csr_col[*A_diag_no_zero_element] = A_csr_col[j];
                A_diag_csr_val[*A_diag_no_zero_element] = A_csr_val[j];

                (*A_diag_no_zero_element)++;
            }
        }
    }

    //最后我们将row数组的最后一个元素
    A_diag_csr_row[A_size] = *A_diag_no_zero_element;
}

//获取包括对角线的上三角矩阵部分
void martix_csr_get_diag_triu(float* A_csr_val, int* A_csr_row, 
int* A_csr_col, int A_no_zero_element, int A_size, 
float* A_diag_triu_csr_val, int* A_diag_triu_csr_row,int* A_diag_triu_csr_col, 
int* A_diag_triu_no_zero_element){
    //遍历行索引，然后再嵌套遍历列索引
    //分别是行索引和列索引
    int i;
    int j;

    *A_diag_triu_no_zero_element = 0;

    //遍历行索引
    //行索引一共是0-size共size+1个，我们就遍历到索引size-1
    for(i = 0; i < A_size ; i++){
        
        //A_triu_csr_row是从0开始的，每次我们根据有效元素的数量，不断更新新的元素
        A_diag_triu_csr_row[i] = *A_diag_triu_no_zero_element;
        
        //遍历所有列
        for(j = A_csr_row[i]; j < A_csr_row[i+1]; j++){
            //我们看当前的列号大于行号，那就是上三角的部分
            if(A_csr_col[j] >= i){
                //这里说明这个节点就是上三角矩阵的元素
                A_diag_triu_csr_col[*A_diag_triu_no_zero_element] = A_csr_col[j];
                A_diag_triu_csr_val[*A_diag_triu_no_zero_element] = A_csr_val[j];

                (*A_diag_triu_no_zero_element)++;
            }
        }
    }

    //最后我们将row数组的最后一个元素
    A_diag_triu_csr_row[A_size] = *A_diag_triu_no_zero_element;
}

//获取包括对角线的下三角部分
void martix_csr_get_diag_tril(float* A_csr_val, int* A_csr_row, 
int* A_csr_col, int A_no_zero_element, int A_size, 
float* A_diag_tril_csr_val, int* A_diag_tril_csr_row,int* A_diag_tril_csr_col, 
int* A_diag_tril_no_zero_element){
    //遍历行索引，然后再嵌套遍历列索引
    //分别是行索引和列索引
    int i;
    int j;

    *A_diag_tril_no_zero_element = 0;

    //遍历行索引
    //行索引一共是0-size共size+1个，我们就遍历到索引size-1
    for(i = 0; i < A_size ; i++){
        
        //A_triu_csr_row是从0开始的，每次我们根据有效元素的数量，不断更新新的元素
        A_diag_tril_csr_row[i] = *A_diag_tril_no_zero_element;
        
        //遍历所有列
        for(j = A_csr_row[i]; j < A_csr_row[i+1]; j++){
            //我们看当前的列号大于行号，那就是上三角的部分
            if(A_csr_col[j] <= i){
                //这里说明这个节点就是上三角矩阵的元素
                A_diag_tril_csr_col[*A_diag_tril_no_zero_element] = A_csr_col[j];
                A_diag_tril_csr_val[*A_diag_tril_no_zero_element] = A_csr_val[j];

                (*A_diag_tril_no_zero_element)++;
            }
        }
    }

    //最后我们将row数组的最后一个元素
    A_diag_tril_csr_row[A_size] = *A_diag_tril_no_zero_element;
}

#endif